import useComponentTracker from './useComponentTracker';
import useCrudActions from './useCrudActions';
import useCrudNodes from './useCrudNodes';
import useCrudState from './useCrudState';

// #region 基础配置
const defaultConfig = {
  immediate: true, // 组件创建时是否立即获取列表
  keyConfig: {
    page: 'page',
    limit: 'limit',
    id: 'id',
    rowName: null,
    editId: null,
    children: 'children',
    status: 'status',
  },
  defaultOptions: {
    listPath: 'items', // 列表接口路径
    listPathNoPaging: '', // 无分页列表接口路径
    totalPath: 'total', // 分页总条数路径
    detailDataPath: '', // 详情接口数据字段路径
  },
  events: {
    editLoaded: (details) => {}, // 编辑时回显数据完成后的回调事件
    beforeUpdateList: (params) => {}, // 更新列表前的回调事件
    updateListResolve: (res) => {}, // 更新列表后的回调事件
    saveBefore: () => {
      return true;
    }, // 提交前的回调事件, 可以返回false阻止提交
  },
};
// #endregion

// 自定义Crud组件
/**
 * @param {object} config 配置项
 * @param {object} config.keyConfig 主键配置
 * @param {object} config.defaultOptions 默认配置
 * @param {object} config.events 事件配置
 * @param {Function} config.events.editLoaded 编辑时回显数据完成后的回调事件
 *
 * @param {object} apis 接口
 * @param {Function} apis.add 新增接口
 * @param {Function} apis.edit 修改接口
 * @param {Function} apis.remove 删除接口
 * @param {Function} apis.details 详情接口
 * @param {Function} apis.list 列表接口
 */
export default function useCrud(config = {}, apis = {}) {
  // #region 状态管理
  const newConfig = mergeConfig(defaultConfig, config);
  const state = useCrudState(newConfig);
  const componentTracker = useComponentTracker();

  const refs = reactive({});
  const slotsProps = reactive({});
  // #endregion

  // #region 业务逻辑处理
  const actions = useCrudActions({ config: newConfig, apis, state, componentTracker, refs, slotsProps });
  // #endregion

  // #region 组件创建
  const [slotsNode] = useCrudNodes({ config: newConfig, state, componentTracker, refs, slotsProps, actions });
  // #endregion

  // #region 获取列表
  nextTick(() => {
    if (newConfig.immediate) {
      actions.updateList();
    }
  });
  // #endregion

  return {
    Crud: slotsNode,
    state,
    actions,
    // 有用的hooks想法，帮助外部定义props变量，便于在不使用v-model也能更新props变量
    // 也解决了，格式化配置不单只能在创建组件时获取到props(导致循环场景多次执行)，也能提前处理配置
    hooks: {
      usePreset(presetName, options) {
        usePreset(presetName, options, actions);
      },
      useTableOptions(options) {
        useTableOptions(options, state, slotsProps);
      },
    },
  };
}

function usePreset(presetName, options, actions) {
  actions.state[`${presetName}Options`] = actions.getPresetButton(presetName, options);
}

// 处理表格列配置
function useTableOptions(options, state, slotsProps) {
  state.columns = options
    .map((item) => {
      if ('prop' in item) {
        return {
          key: item.prop,
          label: item.label,
          visible: 'visible' in item ? item.visible : true,
        };
      }
    })
    .filter(Boolean);
  state.tableOptions = computed(() => {
    const showColumns = new Set(slotsProps.rightToolbar.columns.filter((item) => item.visible).map((item) => item.key));
    return options.filter((item) => (item.prop ? showColumns.has(item.prop) : true));
  });
}

function mergeConfig(defaultConfig, config) {
  function deepMerge(target, source) {
    const result = { ...target };

    for (const key in source) {
      if (source.hasOwnProperty(key)) {
        const sourceValue = source[key];
        const targetValue = result[key];

        // 如果源值和目标值都是对象且不为null，则递归合并
        if (isObject(sourceValue) && isObject(targetValue)) {
          result[key] = deepMerge(targetValue, sourceValue);
        } else {
          // 否则直接覆盖
          result[key] = sourceValue;
        }
      }
    }

    return result;
  }

  function isObject(obj) {
    return obj !== null && typeof obj === 'object' && !Array.isArray(obj);
  }

  return deepMerge(defaultConfig, config);
}